package cc.autoapi.pucong.auto.flow.provider.api.controller;

import cc.autoapi.pucong.auto.flow.core.flow.execNode.eventBus.ISubscriber;
import cc.autoapi.pucong.auto.flow.core.flow.execNode.streamBus.IStreamSubscriber;
import cc.autoapi.pucong.auto.flow.core.root.exception.AutoFlowBaseController;
import cc.autoapi.pucong.auto.flow.core.root.exception.AutoFlowExceptionHandler;
import cc.autoapi.pucong.auto.flow.core.root.utils.Res;
import cc.autoapi.pucong.auto.flow.provider.api.manager.ApiExecManager;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @author pucong
 * @description 接口信息 controller
 * @create 2024-09-24
 */
@RestController
@Validated
@RequestMapping("/api/exec")
@Slf4j
public class ApiExecController extends AutoFlowBaseController implements AutoFlowExceptionHandler{

    @Resource
    private ApiExecManager apiExecManager;

    @RequestMapping("/apiExec/**")
    public Object serviceExec(HttpServletRequest request,
                              @RequestHeader(required = false) Map<String, String> headerMap,
                              @RequestBody(required = false) Map<String, Object> bodyMap,
                              @RequestParam(required = false) Map<String, Object> queryMap) {
        Object json = apiExecManager.serviceExec(request, headerMap, bodyMap, queryMap);
        if (json instanceof IStreamSubscriber) {
            StringBuffer stringBuffer = new StringBuffer();
            IStreamSubscriber iSubscriber = (IStreamSubscriber) json;
            AtomicReference<Boolean> run = new AtomicReference<>(true);
            iSubscriber.emitter(message -> {
                try {
                    stringBuffer.append(message);
                    stringBuffer.append("\n");
                } catch (Exception e) {
                    log.error("流式输出失败", e);
                }
            }, () -> {
                log.info("流式结束结束输出");
                run.set(false);
            });
            do {
                try {
                    Thread.sleep(300);
                } catch (Exception e) {
                }
            } while (run.get());
            return Res.ok(stringBuffer.toString());
        }
        return Res.ok(json);
    }

    @RequestMapping("/apiExecStream/**")
    public void serviceExecStream(HttpServletRequest request,
                                  @RequestHeader(required = false) Map<String, String> headerMap,
                                  @RequestBody(required = false) Map<String, Object> bodyMap,
                                  @RequestParam(required = false) Map<String, Object> queryMap,
                                  HttpServletResponse response) {
        Object json = apiExecManager.serviceExec(request, headerMap, bodyMap, queryMap);
        if (json instanceof ISubscriber) {
            response.setContentType("text/event-stream");
            response.setCharacterEncoding("UTF-8");
            IStreamSubscriber iSubscriber = (IStreamSubscriber) json;
            AtomicReference<Boolean> run = new AtomicReference<>(true);
            iSubscriber.emitter(message -> {
                try {
                    // 每次只输出一个词,每个片段以data: 开头，以\n\n结尾
                    response.getWriter().write(message + "\n\n");
                    response.getWriter().flush();
                } catch (Exception e) {
                    log.error("流式输出失败", e);
                }
            }, () -> {
                log.info("流式结束结束输出");
                run.set(false);
            });
            do {
                try {
                    Thread.sleep(300);
                } catch (Exception e) {
                }
            } while (run.get());
        }
    }
}
